package de.kraenksoft.android.cinemaExample.presenters;

import static de.kraenksoft.android.cinemaExample.fakes.FakeTheaterFactory.createTheaterScreeningsEmtpyDayBetween;
import static de.kraenksoft.android.cinemaExample.fakes.FakeTheaterFactory.createTheaterScreeningsOnlyToday;
import static de.kraenksoft.android.cinemaExample.fakes.FakeTheaterFactory.createTheaterScreeningsPastDays;
import static de.kraenksoft.android.cinemaExample.fakes.FakeTheaterFactory.createTheaterScreeningsTwoDays;
import static de.kraenksoft.android.cinemaExample.fakes.FakeTheaterFactory.createTheaterScreeningsMultipleTimes;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

import de.kraenksoft.android.cinemaExample.fakes.FakeTheaterFactory;
import de.kraenksoft.android.cinemaExample.fakes.MovieListViewFake;
import de.kraenksoft.android.cinemaExample.views.MovieListView;

public class MovieListPresenterImplTests {
	
	private MovieListPresenter presenter;
	private MovieListViewFake fakeView;
	
	private void assertDataOfFirstDaySet() {
		List<Map<String, String>> movies = fakeView.getMovies();
		assertNotNull(movies);
		assertEquals(1, movies.size());
		assertEquals(FakeTheaterFactory.MOVIENAME, movies.get(0).get(MovieListView.MOVIENAMEKEY));
		assertEquals(FakeTheaterFactory.FIRSTTIME, movies.get(0).get(MovieListView.MOVIESCREENINGSKEY));
	}
	
	private void assertDataOfSecondDaySet() {
		List<Map<String, String>> movies = fakeView.getMovies();
		assertNotNull(movies);
		assertEquals(1, movies.size());
		assertEquals(FakeTheaterFactory.MOVIENAME, movies.get(0).get(MovieListView.MOVIENAMEKEY));
		assertEquals(FakeTheaterFactory.SECONDTIME, movies.get(0).get(MovieListView.MOVIESCREENINGSKEY));
		
	}
	
	private void assertNoDataSet() {
		List<Map<String, String>> movies = fakeView.getMovies();
		assertEquals(0, movies.size());
	}
	
	private void assertMutipleTimesSet() {
		List<Map<String, String>> movies = fakeView.getMovies();
		assertNotNull(movies);
		assertEquals(1, movies.size());
		assertEquals(FakeTheaterFactory.MOVIENAME, movies.get(0).get(MovieListView.MOVIENAMEKEY));
		assertEquals(FakeTheaterFactory.MULTIPLETIMES, movies.get(0).get(MovieListView.MOVIESCREENINGSKEY));
		
	}

	@Before  
	public void runBeforeEveryTest() {  
		presenter = new MovieListPresenterImpl();
		fakeView = new MovieListViewFake();
	} 
	
	@Test
	public void testNoDataSet() {
		presenter.setView(fakeView);
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertEquals("Kein Kinoprogramm geladen.", fakeView.getCaption());
		assertNoDataSet();
	}
	
	@Test
	public void testModelSetAfterView(){
		presenter.setView(fakeView);
		presenter.setModel(createTheaterScreeningsOnlyToday());
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertFalse("Kein Kinoprogramm geladen.".equals(fakeView.getCaption()));
		assertDataOfFirstDaySet();
	}

	
	
	@Test
	public void testViewSetAfterModel(){
		presenter.setModel(createTheaterScreeningsOnlyToday());
		presenter.setView(fakeView);
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertFalse("Kein Kinoprogramm geladen.".equals(fakeView.getCaption()));
		assertDataOfFirstDaySet();
	}
	
	@Test
	public void testScreeningsOnlyToday(){
		presenter.setModel(createTheaterScreeningsOnlyToday());
		presenter.setView(fakeView);
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertFalse("Kein Kinoprogramm geladen.".equals(fakeView.getCaption()));
		assertDataOfFirstDaySet();
	}
	
	@Test
	public void testResetNoDataSet(){
		presenter.setModel(createTheaterScreeningsOnlyToday());
		presenter.setView(fakeView);
		presenter.setModel(null);
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertTrue("Kein Kinoprogramm geladen.".equals(fakeView.getCaption()));
		assertNoDataSet();
	}

	@Test
	public void testScreeningsTwoDays(){
		presenter.setModel(createTheaterScreeningsTwoDays());
		presenter.setView(fakeView);
		
		assertTrue(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertTrue(fakeView.getCaption().startsWith("Heute"));
		assertDataOfFirstDaySet();
	}
	
	@Test
	public void testScreeningsTwoDaysSwitchToNextDay(){
		presenter.setModel(createTheaterScreeningsTwoDays());
		presenter.setView(fakeView);
		presenter.nextDayClicked();
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertTrue(fakeView.isLastDayBtnVisible());
		assertTrue(fakeView.getCaption().startsWith("Morgen"));
		assertDataOfSecondDaySet();
	}

	@Test
	public void testScreeningsTwoDaysSwitchToNextDayAndBack(){
		presenter.setModel(createTheaterScreeningsTwoDays());
		presenter.setView(fakeView);
		presenter.nextDayClicked();
		presenter.lastDayClicked();
		
		assertTrue(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertTrue(fakeView.getCaption().startsWith("Heute"));
		assertDataOfFirstDaySet();
	}
	
	@Test
	public void testScreeningsOnlyPastDays(){
		presenter.setModel(createTheaterScreeningsPastDays());
		presenter.setView(fakeView);
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertTrue(fakeView.getCaption().startsWith("Heute"));
		assertNoDataSet();
	}
	
	@Test
	public void testScreeningsEmptyDayBetween(){
		presenter.setModel(createTheaterScreeningsEmtpyDayBetween());
		presenter.setView(fakeView);
		presenter.nextDayClicked();
		
		assertTrue(fakeView.isNextDayBtnVisible());
		assertTrue(fakeView.isLastDayBtnVisible());
		assertTrue(fakeView.getCaption().startsWith("Morgen"));
		assertNoDataSet();
	}
	
	@Test
	public void testScreeningsMultipleTimes(){
		presenter.setModel(createTheaterScreeningsMultipleTimes());
		presenter.setView(fakeView);
		
		assertFalse(fakeView.isNextDayBtnVisible());
		assertFalse(fakeView.isLastDayBtnVisible());
		assertTrue(fakeView.getCaption().startsWith("Heute"));
		assertMutipleTimesSet();
	}
}
